package com.xsq.wifi.utils;


import android.util.Log;

import com.xsq.wifi.callback.Callbacks;
import com.xsq.wifi.model.DeviceVideoListModel;
import com.xsq.wifi.model.WifiListModel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * 编写人：李振德
 * 创建时间：2025/5/16
 */

public class WifiListFetcher {
    private static final String TAG = "WifiListFetcher";

    private static final byte PROTOCOL_VERSION = 0x01;
    private static final short PCP_STA_OK = 0x0001;

    //扫描WIFI
    public static void fetchWifiList(String deviceIp, byte cmd, Callbacks.WifiListCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp, cmd, null, false);
                String jsonStr = new String(response.data, "UTF-8");
                JSONObject json = new JSONObject(jsonStr);

                List<WifiListModel> wifiList = new ArrayList<>();
                Iterator<String> keys = json.keys();
                while (keys.hasNext()) {
                    String ssid = keys.next();
                    if (!ssid.isEmpty()) {
                        wifiList.add(new WifiListModel(ssid, json.getInt(ssid)));
                    }
                }

                Collections.sort(wifiList, (a, b) -> Integer.compare(b.getRssi(), a.getRssi()));
                callback.onSuccess(wifiList);
            } catch (Exception e) {
                Log.e(TAG, "fetchWifiList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 配置WiFi
    public static void configureWifi(String deviceIp, String ssid, String password, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte[] payload = (ssid + "," + password).getBytes("UTF-8");
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_WIFISTA_SET, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "configureWifi error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 获取视频列表
    public static void getVideoList(String deviceIp, Callbacks.VideoListCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERLIST_GET, null, false);
                String jsonStr = new String(response.data, "UTF-8");
                JSONArray jsonArray = new JSONArray(jsonStr);

                List<String> videoList = new ArrayList<>();
                for (int i = 0; i < jsonArray.length(); i++) {
                    videoList.add(jsonArray.getString(i));
                }
                callback.onSuccess(videoList);
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 批量获取缩略图
    public static void getVideoThumbnailsBatch(String deviceIp, List<String> videoPaths, Callbacks.VideoImgListBatchCallback callback) {
        new Thread(() -> {
            List<DeviceVideoListModel> results = new ArrayList<>();
            for (String path : videoPaths) {
                try {
                    String fileName = new File(path).getName();
                    byte[] payload = fileName.getBytes("UTF-8");

                    NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                            ProtocolConstants.CMD_FILETHUMBNAIL_GET, payload, true);

                    if (response.data.length > 0) {
                        results.add(new DeviceVideoListModel(response.data, path));
                    }
                } catch (Exception e) {
                    Log.e(TAG, "Failed to get thumbnail: " + path, e);
                }
            }
            callback.onSuccess(results);
        }).start();
    }

//    // 批量获取缩略图
//    public static void getVideoThumbnailsBatch(String deviceIp, List<String> videoPaths, Callbacks.VideoImgListBatchCallback callback) {
//        new Thread(() -> {
//            List<DeviceVideoListModel> results = new ArrayList<>();
//            PersistentConnection connection = PersistentConnection.getInstance();
//
//            try {
//                connection.connect(deviceIp); // 确保连接已建立
//
//                for (String path : videoPaths) {
//                    try {
//                        String fileName = new File(path).getName();
//                        byte[] payload = fileName.getBytes("UTF-8");
//
//                        PersistentConnection.Response response = connection.sendRequest(
//                                ProtocolConstants.CMD_FILETHUMBNAIL_GET,
//                                payload
//                        );
//
//                        if (response.data.length > 0) {
//                            results.add(new DeviceVideoListModel(response.data, path));
//                        }
//                    } catch (Exception e) {
//                        Log.e(TAG, "Failed to get thumbnail: " + path, e);
//                    }
//                }
//                callback.onSuccess(results);
//            } catch (IOException e) {
//                callback.onFailure(e.getMessage());
//            }
//        }).start();
//    }


    //播放指定路径视频
    public static void playvideo(String deviceIp, String path, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte[] payload = path.getBytes("UTF-8");
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERFILE, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "configureWifi error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 获取播放器状态
    public static void getPlayStatus(String deviceIp, Callbacks.VideoStatusCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERSTATUS_GET, null, false);
                String jsonStr = new String(response.data, "UTF-8");
                Log.v("zadenene",jsonStr);
                callback.onSuccess(jsonStr);
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    //暂停开始播放(0暂停，1播放)
    public static void setPlayStatus(String deviceIp, String isbofang, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                //byte[] payload = isbofang.getBytes("UTF-8");
                byte[] payload = new byte[]{(byte) (isbofang.equals("1") ? 0x0001 : 0x0000)};
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_PLAYERPAUSE, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "configureWifi error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 播放上一曲
    public static void setVideoUp(String deviceIp, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERPREV, null, false);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }


    // 播放下一曲
    public static void setVideoDown(String deviceIp, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERNEXT, null, false);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

//    // 刷新播放列表
//    public static void updateVideoList(String deviceIp, Callbacks.ConfigCallback callback) {
//        new Thread(() -> {
//            try {
//                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
//                        ProtocolConstants.CMD_PLAYERLIST_UPDATE, null, false);
//                callback.onSuccess();
//            } catch (Exception e) {
//                Log.e(TAG, "error", e);
//                callback.onFailure(e.getMessage());
//            }
//        }).start();
//    }

    // 刷新播放列表
    public static void updateVideoList(String deviceIp, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_PLAYERLIST_UPDATE, null, false);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 获取设备状态
    public static void getWorkStatus(String deviceIp, Callbacks.VideoStatusCallback callback) {
        new Thread(() -> {
            try {
                NetworkHelper.Response response = NetworkHelper.sendRequest(deviceIp,
                        ProtocolConstants.CMD_WORKSTATUS_GET, null, false);
                String jsonStr = new String(response.data, "UTF-8");
                callback.onSuccess(jsonStr);
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 亮度设置
    public static void setBrightness(String deviceIp,int jindu,Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte brightnessByte = (byte) jindu;

                // 3. 构造payload (假设只需要亮度值)
                byte[] payload = new byte[]{brightnessByte};
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_BRIGHTNESS_SET, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 角度设置
    public static void setAngle(String deviceIp,int jindu,Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte brightnessByte = (byte) jindu;

                // 3. 构造payload (假设只需要亮度值)
                byte[] payload = new byte[]{brightnessByte};
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_DISPANGLE_SET, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 音量设置
    public static void setVolume(String deviceIp,int jindu,Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte brightnessByte = (byte) jindu;

                // 3. 构造payload (假设只需要亮度值)
                byte[] payload = new byte[]{brightnessByte};
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_VOLUME_SET, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "getVideoList error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    //开关屏(0息屏，1打开)
    public static void setDisplay(String deviceIp, String isbofang, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                //byte[] payload = isbofang.getBytes("UTF-8");
                byte[] payload = new byte[]{(byte) (isbofang.equals("1") ? 0x0001 : 0x0000)};
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_DISP_ON, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "configureWifi error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 文件传输开始
    public static void startFileTransfer(String deviceIp, String filename, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                byte[] payload = (filename).getBytes("UTF-8");
                NetworkHelper.Response response = NetworkHelper.sendRequest1(deviceIp,
                        ProtocolConstants.CMD_FILETRANS_START, payload, true);
                callback.onSuccess();
            } catch (Exception e) {
                Log.e(TAG, "configureWifi error", e);
                callback.onFailure(e.getMessage());
            }
        }).start();
    }

    // 文件传输方法（分块传输）
    public static void transferVideoFile(String deviceIp, File videoFile, Callbacks.ConfigCallback callback) {
        new Thread(() -> {
            try {
                // 1. 分块传输文件
                transferFileInChunks(deviceIp, videoFile);
                callback.onSuccess();
                Log.e(TAG, "传输完成");
            } catch (Exception e) {
                Log.e(TAG, "文件传输失败", e);
                callback.onFailure("传输错误: " + e.getMessage());
            }
        }).start();
    }

    private static void transferFileInChunks(String deviceIp, File file) throws IOException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
            byte[] buffer = new byte[8192]; // 8KB分块
            int bytesRead;
            int chunkIndex = 0;

            while ((bytesRead = fis.read(buffer)) != -1) {
                // 为每个分块创建独立短连接
                sendFileChunk(deviceIp, chunkIndex++,
                        Arrays.copyOf(buffer, bytesRead));
            }
        } finally {
            if (fis != null) fis.close();
        }
    }

    private static void sendFileChunk(String deviceIp, int chunkIndex, byte[] chunkData)
            throws IOException {
        Socket socket = null;
        try {
            // 1. 建立连接（短连接）
            socket = new Socket();
            socket.connect(new InetSocketAddress(deviceIp, 3333), 10000);
            socket.setSoTimeout(15000);

//            ByteBuffer requestBuffer = ByteBuffer.allocate(8 + (chunkData != null ? chunkData.length : 0));
//            requestBuffer.order(ByteOrder.LITTLE_ENDIAN);
//            requestBuffer.put(PROTOCOL_VERSION);
//            requestBuffer.put(chunkData);
//            short controlValue = (short) 0x0000;
//            requestBuffer.putShort(controlValue);
//            requestBuffer.putInt(chunkData != null ? chunkData.length : 0);
//            if (chunkData != null) {
//                requestBuffer.put(chunkData);
//            }

            // 2. 构建协议头
            ByteBuffer header = ByteBuffer.allocate(12)
                    .order(ByteOrder.BIG_ENDIAN)
                    .put(PROTOCOL_VERSION)
                    .put(ProtocolConstants.CMD_FILETRANS_DATA)
                    .putShort((short)0x0000) // control字段
                    .putInt(chunkData.length)
                    .putInt(chunkIndex);     // 新增分块序号

            // 3. 发送数据
            OutputStream out = socket.getOutputStream();
            out.write(header.array());
            out.write(chunkData);
            out.flush();

            // 4. 接收响应（参考可靠实现）
//            byte[] respHeader = readExactly(socket.getInputStream(), 8);
//            ByteBuffer respBuffer = ByteBuffer.wrap(respHeader)
//                    .order(detectByteOrder(respHeader));
//
//            byte version = respBuffer.get();
//            byte cmd = respBuffer.get();
//            short status = respBuffer.getShort();
//            int dataLen = respBuffer.getInt();
//
//            if (version != PROTOCOL_VERSION || cmd != ProtocolConstants.CMD_FILETRANS_DATA) {
//                throw new IOException("协议不匹配");
//            }
//            if (status != PCP_STA_OK) {
//                throw new IOException("设备返回错误状态: 0x" + Integer.toHexString(status));
//            }

        } finally {
            closeSocket(socket);
        }
    }

    // 从参考代码提取的可靠读取方法
    private static byte[] readExactly(InputStream in, int length) throws IOException {
        byte[] data = new byte[length];
        int offset = 0;
        while (offset < length) {
            int read = in.read(data, offset, length - offset);
            if (read == -1) {
                throw new EOFException("Premature EOF");
            }
            offset += read;
        }
        return data;
    }

    private static ByteOrder detectByteOrder(byte[] header) {
        ByteBuffer buffer = ByteBuffer.wrap(header).order(ByteOrder.BIG_ENDIAN);
        short statusBigEndian = buffer.getShort(2);
        return statusBigEndian == 0x0100 ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
    }

    static void closeSocket(Socket socket) {
        if (socket != null) {
            try {
                socket.setSoLinger(true, 0);
                try { socket.shutdownInput(); } catch (IOException ignored) {}
                try { socket.shutdownOutput(); } catch (IOException ignored) {}
                socket.close();
            } catch (IOException e) {
                Log.w(TAG, "Error closing socket", e);
            }
        }
    }

}